#pragma once 

#include <iostream>
#include <string>
#include <list>
#include <memory>
#include <sys/socket.h>
#include <sys/types.h>
#include "Inetaddr.hpp"
#include "Log.hpp"

using namespace LogModule;

class UserInterface
{
public:
    virtual ~UserInterface() = default;
    virtual void Sendto(int sockfd, const std::string &message) = 0;
    virtual bool operator == (const InetAddr &u) = 0;
};

class User : public UserInterface
{
public:
    User(const InetAddr& id)
        :_id(id)
    {}
    
    void Sendto(int sockfd, const std::string &message) override
    {
        LOG(LogLevel::DEBUG) << "send message to" << _id.Addr() << ", info is: " << message;
        ssize_t n = sendto(sockfd, message.c_str(), message.size(), 0, _id.NetAddr(), _id.NetAddrLen());
        if (n < 0)
        {
            LOG(LogLevel::ERROR) << "sendto error";
        }
    }

    bool operator == (const InetAddr &u) override
    {
        return _id == u;
    }
    ~User()
    {

    }
private:
    InetAddr _id;
};

class UserManage
{
public:
    UserManage()
    {}
    
    void AddUser(const InetAddr &id)
    {
        for (auto &user : _online_user)
        {
            LOG(LogLevel::INFO) << id.Addr() << "用户已经存在";
            if (*user == id) return;
        }
        LOG(LogLevel::INFO) << "新增用户：" << id.Addr();
        _online_user.push_back(std::make_shared<User>(id));
    }
    
    void DelUser(const InetAddr &id)
    {

    }

    void Router(int sockfd, const std::string &message)
    {
        for (auto &user : _online_user)// 通过基类的指针或引用，调用的是派生类中对应虚函数的重写，这就是多态
        {
            user->Sendto(sockfd, message);
        }
    }

    ~UserManage()
    {}
private:
    std::list<std::shared_ptr<UserInterface>> _online_user;
};
